#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <unordered_map>
#include <algorithm>
using namespace std;
const int ALPHABET_SIZE = 26;
struct TrieNode {
TrieNode* children[ALPHABET_SIZE];
unordered_map<int, vector<pair<string, int>>> patterns;
TrieNode* fail;
TrieNode() {
for (int i = 0; i < ALPHABET_SIZE; ++i) {
children[i] = nullptr;
}
fail = nullptr;
}
};
void insertTrie(TrieNode* root, const string& pattern, const string& replacement, int count) {
TrieNode* node = root;
for (char c : pattern) {
int index = c - 'a';
if (!node->children[index]) {
node->children[index] = new TrieNode();
}
node = node->children[index];
}
int len = pattern.length();
node->patterns[len].emplace_back(replacement, count);
}
void buildFailureLinks(TrieNode* root) {
queue<TrieNode*> q;
for (int i = 0; i < ALPHABET_SIZE; ++i) {
if (root->children[i]) {
root->children[i]->fail = root;
q.push(root->children[i]);
} else {
root->children[i] = root;
}
}
while (!q.empty()) {
TrieNode* current = q.front();
q.pop();
for (int i = 0; i < ALPHABET_SIZE; ++i) {
if (current->children[i]) {
TrieNode* next = current->children[i];
TrieNode* temp = current->fail;
while (!temp->children[i]) {
temp = temp->fail;
}
next->fail = temp->children[i];
q.push(next);
}
}
}
}
long long query(TrieNode* root, const string& text, const string& target) {
long long count = 0;
int n = text.size();
int m = target.size();
if (n != m) return 0;
vector<int> lcp(n + 1, 0);
for (int i = n - 1; i >= 0; --i) {
if (text[i] == target[i]) {
lcp[i] = lcp[i + 1] + 1;
} else {
lcp[i] = 0;
}
}
vector<int> lcs(n + 1, 0);
for (int i = 0; i < n; ++i) {
if (text[i] == target[i]) {
lcs[i] = (i > 0 ? lcs[i - 1] : 0) + 1;
} else {
lcs[i] = 0;
}
}
TrieNode* current = root;
for (int i = 0; i < n; ++i) {
int index = text[i] - 'a';
while (!current->children[index]) {
current = current->fail;
}
current = current->children[index];
TrieNode* temp = current;
while (temp != root) {
for (auto& [len, repls] : temp->patterns) {
if (i - len + 1 < 0) continue;
int start = i - len + 1;
int end = i;
bool valid = true;
if (start > 0 && lcs[start - 1] < start) {
valid = false;
}
if (end < n - 1 && lcp[end + 1] < n - end - 1) {
valid = false;
}
if (valid) {
for (auto& [repl, cnt] : repls) {
if (target.substr(start, len) == repl) {
count += cnt;
}
}
}
}
temp = temp->fail;
}
}
return count;
}
int main() {
freopen( "replace.in","r",stdin );
freopen( "replace.out","w",stdout );
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, q;
cin >> n >> q;
TrieNode* root = new TrieNode();
unordered_map<string, unordered_map<string, int>> patternCount;
for (int i = 0; i < n; ++i) {
string a, b;
cin >> a >> b;
patternCount[a][b]++;
}
for (const auto& entry : patternCount) {
const string& pattern = entry.first;
int totalCount = 0;
for (const auto& replCount : entry.second) {
totalCount += replCount.second;
}
insertTrie(root, pattern, "", totalCount);
for (const auto& replCount : entry.second) {
insertTrie(root, pattern, replCount.first, replCount.second);
}
}
buildFailureLinks(root);
for (int i = 0; i < q; ++i) {
string t1, t2;
cin >> t1 >> t2;
cout << query(root, t1, t2) << '\n';
}
return 0;
}